<?php

/**
 * 数据模型基础类
 * 
 * 提供数据模型实用功能，如CURD操作等
 * 
 * @author sutroon <14507247@qq.com>
 * @license http://www.sochishun.com
 * @version $Id: SoWebUtility.php v 1.0 2013-9-3 06:55:42Z sutroon Exp $
 * @package Core
 * @example 
 *  1.普通添加和编辑
 *      // 带表名实例化
 *      $m=new SoDataModule('tUserMember');
 *      // 查询
 *      $this->dm->search('ID=5');
 *      // 两种赋值方式
 *      $this->dm->Title='Title 1';
 *      $this->dm->Param('Content','Content text...','string');
 *      // 添加或编辑,如果已经执行过search方法，则update不用代入查询条件
 *      if($this->dm->add()){ // $this->dm->update('ID=5');
 *          $this->message('添加成功');
 *      }else{
 *          $this->message($this->dm->get_error());
 *      }
 *      // 删除
 *      $this->dm->delete('ID=5');
 *  2.通用添加和编辑
 *      // 空表名实例化
 *      $m=new SoDataModule('');
 *      // 更新
 *      $this->dm->update('tUserMember','Point=Point+5, State=1','ID=5');
 *      // 添加
 *      $this->dm->add('tUserMember','Name=\'User 1\', Sex=0');
 *      // 删除
 *      $this->dm->delete('tUserMember','ID=5');
 *      // 查询
 *      $this->dm->select_array('tUserMember','ID=5','ID, Name');
 *      // 查字段
 *      $this->dm->select_field('tUserMember','State=1','count(ID)');
 *  3.联表操作
 *      // 空表名实例化
 *      $m=new SoDataModule('');
 *      // 联合查询
 *      $this->dm->search('tUserMember u left join tDepartment d on u.DepartmentID=d.ID','u.ID=1','*');
 *      // 联合更新
 *      $this->dm->update('tUserMember u left join tDepartment d on u.DepartmentID=d.ID','u.DepartmentName=d.Name','d.ID=1 and u.DepartmentName is null');
 */
class SoDataModule implements ISoDbHelper {

    /**
     * 当前操作的数据表名称
     * @var type 
     */
    public $tablename;

    /**
     * 参数集
     * @var type 
     */
    public $params = array();

    /**
     * 错误消息收集器
     * @var type 
     */
    public $msg = array();
    
    /**
     * 数据库操作封装对象
     * @var type 
     */
    public $db;

    /**
     * 数据库表名前缀
     * @var type 
     */
    public $db_prefix;

    /*     * *********************************
     * 以下是SoDataModule专属方法
     * ********************************* */

    /**
     * 变量转属性
     * @param type $name
     * @return null
     * @since 1.0.0 2013-9-16
     * @example echo $this->dm->Title;
     */
    public function __get($name) {
        if (isset($this->$name))
            return $this->$name;
        if (array_key_exists($name, $this->params))
            return trim($this->params[$name],"'");
        return null;
    }

    /**
     * 变量转属性
     * @param type $name
     * @param type $value
     * @return type
     * @since 1.0.0 2013-9-16
     * @example $this->dm->Title='Title 1';
     */
    public function __set($name, $value) {
        if (isset($this->$name))
            return $this->$name = $value;
        if (array_key_exists($name, $this->params))
            $this->params[$name] = $value;
    }

    /**
     * 构造方法
     * 
     * @global array $SO_DB_INFO
     * @param bool $auto_connect 是否自动连接数据库
     */
    function __construct($auto_connect=true) {
        global $SO_DB_INFO;
        $this->db_prefix = $SO_DB_INFO['DB_PREFIX'];
        if($auto_connect) $this->connect($SO_DB_INFO);
    }
    
    /**
     * 连接数据库
     * @global type $SO_DB_INFO
     */
    public function connect($db_info=null){
        if($db_info==null){
            global $SO_DB_INFO;
            $db_info=$SO_DB_INFO;
        }
        switch (strtolower($db_info['DB_TYPE'])) {
            case 'mysql':
                $this->db = new SoDbMysql5($db_info);
                break;
        }
    }

    /**
     * 添加一条消息到消息集
     * @param type $msg
     */
    public function add_message($msg) {
        $this->msg[] = $msg;
    }

    /**
     * 添加一条参数
     * @param type $name
     * @param type $v
     * @param type $err
     * @param type $type
     * @return type
     */
    public function add_param($name, $v, $err = '', $type = 'string') {
        if ($err && strlen($v)==0) {
            $this->msg[] = $err;
            return;
        }
        switch ($type) {
            case "int":
                if (!is_numeric($v)) {
                    $this->msg[] = $err ? $err : "字段['$name']不是有效的数值";
                    return;
                }
                $this->params[$name] = $v;
                break;
            default:
                $this->params[$name] = sprintf("'%s'", $v);
                break;
        }
    }

    /**
     * 检测参数是否有效
     * @param type $name
     * @param type $v
     * @param type $type
     * @param type $err
     * @return boolean
     */
    public function check_param($name, $v, $type = 'string', $err = '') {
        if (!$v && $err) {
            $this->msg[] = $err;
            return false;
        }
        return true;
    }

    /**
     * 比较两个变量的值是否相等，如密码和重复密码比较等
     * @param type $v1
     * @param type $v2
     * @param type $err
     * @param type $type
     * @return boolean
     * @demo $this->dm->compare('Password','PasswordConf','两次密码不一致');
     * @since 1.0.0 2013-5-21 sutroon
     */
    public function compare_param($v1, $v2, $err, $type = 'string') {
        if (!$v1 || ($v1 != $v2)) {
            $this->msg[] = $err;
            return false;
        }
        return true;
    }

    /**
     * 检测记录是否存在(模型方法)
     * @param type $table
     * @param type $condition
     * @return type
     */
    public function exists($condition) {
        return $this->db->select_value($this->db_prefix.$this->tablename, $condition, 'count(0)') > 0;
    }

    /**
     * 更新记录(模型方法)
     * @param type $condition
     * @return boolean
     */
    public function update($condition) {
        if (!$condition || $this->msg)
            return false;
        if (!$this->params)
            return false;
        $updates = '';
        foreach ($this->params as $key => $value) {
            $updates.=" $key = $value,";
        }
        $updates = rtrim($updates, ',');
        $this->db->update_records($this->db_prefix.$this->tablename, $updates, (is_numeric($condition) ? "ID = $condition" : $condition));
        return 'SUCCESS';
    }

    /**
     * 插入一条记录并返回记录的主键值(模型方法)
     * @param type $primary
     * @param type $orderby
     * @return boolean
     */
    public function insert($primarysearch = '', $orderby = 'ID desc') {
        if (!$this->params || $this->msg)
            return false;
        $fields = '';
        $values = '';
        foreach ($this->params as $key => $value) {
            $fields.=" $key,";
            $values.=" $value,";
        }
        $fields = rtrim($fields, ',');
        $values = rtrim($values, ',');
        $result = $this->db->insert_record($this->db_prefix.$this->tablename, $fields, $values,'','');
        if (!$primarysearch)
            return $result=='SUCCESS';
        return $this->db->select_value($this->db_prefix.$this->tablename, 'order by ' . $orderby . ' limit 1;', $primarysearch);
    }

    /**
     * 删除记录(模型方法)
     * @param type $search
     * @return type
     */
    public function delete($search) {
        return $this->db->delete_records($this->db_prefix.$this->tablename, $search);
    }

    /**
     * 获取字符串格式的错误消息
     * @param type $splitor
     * @return type
     */
    public function get_error($splitor = '<br />') {
        return implode($splitor, $this->msg);
    }

    /**
     * 检测是否有错误消息
     * @return type
     */
    public function has_error() {
        return count($this->msg) > 0;
    }

    /*     * **************************************
     * 以下是对IDatabaseHelper接口的实现
     * ************************************** */

    public function combin_select_sql($table, $search, $fields = '*') {
        return $this->db->combin_select_sql($table ? $table : $this->db_prefix.$this->tablename, $search, $fields);
    }

    public function delete_records($table, $search) {
        return $this->db->delete_records($table ? $table : $this->db_prefix.$this->tablename, $search);
    }

    public function execute_sql($sql) {
        return $this->db->execute_sql($sql);
    }

    public function get_table_data($table, $crlf = '\r\n') {
        return $this->db->get_table_data($table ? $table : $this->db_prefix.$this->tablename, $crlf);
    }

    public function get_table_structure($table, $isdrop = false, $nl = '\r\n') {
        return $this->db->get_table_structure($table ? $table : $this->db_prefix.$this->tablename, $isdrop, $nl);
    }

    public function insert_record($table, $names, $values, $lastsearch = '', $key = 'ID') {
        return $this->db->insert_record($table ? $table : $this->db_prefix.$this->tablename, $names, $values, $lastsearch, $key);
    }

    public function select_arrayset($table, $search, $fields = '*') {
        return $this->db->select_arrayset($table ? $table : $this->db_prefix.$this->tablename, $search, $fields);
    }

    public function select_column_values($table, $search, $fields = '*', $columnid = 0) {
        return $this->db->select_column_values($table ? $table : $this->db_prefix.$this->tablename, $search, $fields, $columnid);
    }

    public function select_object($table, $search, $field) {
        return $this->db->select_object($table ? $table : $this->db_prefix.$this->tablename, $search, $field);
    }

    public function select_one_row($table, $search, $fields = '*') {
        return $this->db->select_one_row($table ? $table : $this->db_prefix.$this->tablename, $search, $fields);
    }

    public function select_pagingset($pageindex, $pagesize, &$recordcount, $from, $orderby = 'CreatedTime desc', $fields = '*') {
        return $this->db->select_pagingset($pageindex, $pagesize, $recordcount, $from, $orderby, $fields);
    }

    public function select_value($table, $search, $fields = '*', $defv = '') {
        return $this->db->select_value($table ? $table : $this->db_prefix.$this->tablename, $search, $fields, $defv);
    }

    /**
     * 更新记录<br />
     * 成功则返回SUCCESS，否则返回错误消息
     * @param type $table
     * @param type $fields
     * @param type $search
     * @return type
     */
    public function update_records($table, $fields, $search) {
        return $this->db->update_records($table ? $table : $this->db_prefix.$this->tablename, $fields, $search);
    }

    public function show_tables(){
        return $this->db->show_tables();
    }
    public function backup_table_structure($table, $isdrop = false, $nl = '\r\n') {
        return $this->db->backup_table_structure($table, $isdrop, $nl);
    }

    public function backup_table_data($table, $crlf = '\r\n') {
        return $this->db->backup_table_data($table, $crlf);
    }

    public function backup_all_db() {
        return $this->db->backup_all_db();
    }
}

?>
